<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>纯Java生态 EasyAi｜用 EasyAi 和 Milvus 从零搭建 人脸识别 应用</title>
  <link rel="stylesheet" href="https://stackedit.io/style.css" />
</head>

<body class="stackedit">
<div class="stackedit__html"><p><strong>如何从零搭建一个 人脸识别 应用？不妨试试 原生Java人工智能算法：EasyAi + Milvus 的组合拳。</strong></p>
  <h2><a id="_2"></a>本文将使用到的软件和工具包括：</h2>
  <p><strong>EasyAi：人脸特征向量提取<br>
    Milvus：向量数据库用于高效存储和检索数据。</strong></p>
  <p><img src="/easyai-milvus.png" alt="logo"></p>
  <h2><a id="EasyAiJava_9"></a>EasyAi：国内人气最高的Java人工智能算法框架</h2>
  <p>作为纯java开发 Ai 应用的框架，EasyAi无任何依赖，它是一个原生Java人工智能算法框架。首先，它可以Maven一键丝滑引入我们的Java项目，无需任何额外的环境配置与依赖，做到开箱即用。再者，它既有一些我们已经封装好的图像目标检测及人工智能客服的模块，也提供各种深度学习，机器学习，强化学习，启发式学习，矩阵运算，求导函数，求偏导函数等底层算法工具。开发者可以通过简单的学习，就能完成根据自身业务，深度开发符合自己业务的小微模型。</p>
  <h3><a id="EasyAiFaceEasyAi_13"></a>EasyAi-Face：基于Easy-Ai的人脸识别应用</h3>
  <p><strong>一，生成人类平均脸</strong>，将所有人脸样本样本缩放到统一尺寸后，多余的上下截断，不足的进行补0，所有像素通道求和后获取平均数，将样本输出生成平均脸。<br>
    <strong>二，通过事先训练好的人脸定位fastYolo模型</strong>，对目标照片进行一次定位，并设置一个阈值，只有当可信度超过该阈值时才被认为是人脸。<br>
    <strong>三，获取目标照片中可信度最高的人脸定位框</strong>，基于该定位进行人脸位置的二次修正。<br>
    <em><strong>二次修正方案</strong></em>：</p>
  <ol>
    <li>通过粒子群，设置四个特征维度寻求最优解，它们分别是人脸位置左上角的x与y坐标与宽高。自适应函数返回值设置为最小值最优。xy与宽高四维粒子调整活动范围，上下限制为一次定位坐标与宽高的±50像素的范围（自行可调）。</li>
    <li>适应函数计算流程为通过四个维度粒子锁定的坐标将人脸截取下来，将它与先前获取的平均脸按照之前的缩放方案，再次缩放到指定的一个更小的尺寸，并将它们的灰度通道通过softMax将整个矩阵的所有数值概率化。</li>
    <li>对比平均脸与粒子此时锁定人脸灰度概率图像的欧式距离，并返回。让粒子探索（在指定迭代次数中）最小值最优解。</li>
  </ol>
  <p><strong>四，获取人脸特征</strong>，获取最后粒子寻找的最优坐标，根据该坐标将图像截取下来，并截取其从上到下高度的0.7倍的图像位置（将嘴部扔掉，嘴部的稳定性比较差），获取此时图像的LBP局部二值化纹理特征。</p>
  <h2><a id="EasyAiFace__Milvus_25"></a>EasyAi-Face + Milvus搭建人脸识别应用</h2>
  <h3><a id="_27"></a>提取人脸特征</h3>
  <h4><a id="_29"></a>引入依赖</h4>
  <pre><code class="prism language-pom">        &lt;dependency&gt;
            &lt;groupId&gt;org.dromara.easyai&lt;/groupId&gt;
            &lt;artifactId&gt;seeFace&lt;/artifactId&gt;
            &lt;version&gt;1.0.5&lt;/version&gt;
        &lt;/dependency&gt;
</code></pre>
  <h4><a id="Face_38"></a>初始化Face</h4>
  <pre><code class="prism language-java">    <span class="token annotation punctuation">@Bean</span>
    <span class="token keyword">public</span> <span class="token class-name">Face</span> <span class="token function">face</span><span class="token punctuation">(</span><span class="token class-name">FaceConfig</span> faceConfig <span class="token punctuation">)</span><span class="token punctuation">{</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token class-name">StringUtils</span><span class="token punctuation">.</span><span class="token function">isNotBlank</span><span class="token punctuation">(</span>faceConfig<span class="token punctuation">.</span><span class="token function">getAvgFace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token class-name">StringUtils</span><span class="token punctuation">.</span><span class="token function">isNotBlank</span><span class="token punctuation">(</span>faceConfig<span class="token punctuation">.</span><span class="token function">getFaceModel</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
            <span class="token keyword">return</span> <span class="token class-name">FaceFactory</span><span class="token punctuation">.</span><span class="token function">getFace</span><span class="token punctuation">(</span>faceConfig<span class="token punctuation">.</span><span class="token function">getAvgFace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> faceConfig<span class="token punctuation">.</span><span class="token function">getFaceModel</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token punctuation">}</span>
        <span class="token keyword">return</span> <span class="token class-name">FaceFactory</span><span class="token punctuation">.</span><span class="token function">getFace</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>


    <span class="token punctuation">}</span>
</code></pre>
  <h4><a id="_53"></a>提取人脸特征</h4>
  <pre><code class="prism language-java">    <span class="token keyword">private</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Float</span><span class="token punctuation">&gt;</span></span> <span class="token function">getFloats</span><span class="token punctuation">(</span><span class="token class-name">InputStream</span> inputStream<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">ThreeChannelMatrix</span> m <span class="token operator">=</span> <span class="token class-name">Picture</span><span class="token punctuation">.</span><span class="token function">getThreeMatrix</span><span class="token punctuation">(</span>inputStream<span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">ErrorMessage</span> errorMessage <span class="token operator">=</span> face<span class="token punctuation">.</span><span class="token function">look</span><span class="token punctuation">(</span>m<span class="token punctuation">,</span> idWorker<span class="token punctuation">.</span><span class="token function">nextId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token number">30</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">final</span> <span class="token class-name">Matrix</span> feature <span class="token operator">=</span> errorMessage<span class="token punctuation">.</span><span class="token function">getFaceMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getFeature</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token class-name">MatrixUtil</span><span class="token punctuation">.</span><span class="token function">matrixToFloatList</span><span class="token punctuation">(</span>feature<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre>
  <h4><a id="_63"></a>存到向量库</h4>
  <pre><code class="prism language-java">    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">initUserVector</span><span class="token punctuation">(</span><span class="token class-name">UserDTO</span> userDTO<span class="token punctuation">,</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Float</span><span class="token punctuation">&gt;</span></span> features<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">&gt;</span></span> names <span class="token operator">=</span> <span class="token class-name">Collections</span><span class="token punctuation">.</span><span class="token function">singletonList</span><span class="token punctuation">(</span>userDTO<span class="token punctuation">.</span><span class="token function">getUserName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Long</span><span class="token punctuation">&gt;</span></span> userIds <span class="token operator">=</span> <span class="token class-name">Collections</span><span class="token punctuation">.</span><span class="token function">singletonList</span><span class="token punctuation">(</span>userDTO<span class="token punctuation">.</span><span class="token function">getUserId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">&gt;</span></span> getFaceUrl <span class="token operator">=</span> <span class="token class-name">Collections</span><span class="token punctuation">.</span><span class="token function">singletonList</span><span class="token punctuation">(</span>userDTO<span class="token punctuation">.</span><span class="token function">getFaceUrl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">&gt;</span></span> getFaceFeatureUrl <span class="token operator">=</span> <span class="token class-name">Collections</span><span class="token punctuation">.</span><span class="token function">singletonList</span><span class="token punctuation">(</span>userDTO<span class="token punctuation">.</span><span class="token function">getFaceFeatureUrl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">List</span><span class="token punctuation">&lt;</span><span class="token class-name">Float</span><span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> vectors <span class="token operator">=</span> <span class="token class-name">Collections</span><span class="token punctuation">.</span><span class="token function">singletonList</span><span class="token punctuation">(</span>features<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Field</span><span class="token punctuation">&gt;</span></span> fields <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        fields<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Field</span><span class="token punctuation">(</span><span class="token string">"vector"</span><span class="token punctuation">,</span> vectors<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        fields<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Field</span><span class="token punctuation">(</span><span class="token string">"face_url"</span><span class="token punctuation">,</span> getFaceUrl<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        fields<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Field</span><span class="token punctuation">(</span><span class="token string">"face_feature_url"</span><span class="token punctuation">,</span> getFaceFeatureUrl<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        fields<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Field</span><span class="token punctuation">(</span><span class="token string">"user_id"</span><span class="token punctuation">,</span> userIds<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        fields<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Field</span><span class="token punctuation">(</span><span class="token string">"user_name"</span><span class="token punctuation">,</span> names<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">InsertParam</span> insertParam <span class="token operator">=</span> <span class="token class-name">InsertParam</span><span class="token punctuation">.</span><span class="token function">newBuilder</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">withCollectionName</span><span class="token punctuation">(</span>milvusConfig<span class="token punctuation">.</span><span class="token function">getCollectionName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">withFields</span><span class="token punctuation">(</span>fields<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>milvusClient<span class="token punctuation">.</span><span class="token function">insert</span><span class="token punctuation">(</span>insertParam<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre>
  <h4><a id="L2_83"></a>【识别人脸】人脸特征L2相似性查找</h4>
  <pre><code class="prism language-java">    <span class="token keyword">public</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">UserDTO</span><span class="token punctuation">&gt;</span></span> <span class="token function">search</span><span class="token punctuation">(</span><span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Float</span><span class="token punctuation">&gt;</span></span> floatList<span class="token punctuation">,</span> <span class="token class-name">Integer</span> topK<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">final</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">SearchResultsWrapper<span class="token punctuation">.</span>IDScore</span><span class="token punctuation">&gt;</span></span> idScoreList <span class="token operator">=</span> vectorService<span class="token punctuation">.</span><span class="token function">search</span><span class="token punctuation">(</span>floatList<span class="token punctuation">,</span> topK<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">UserDTO</span><span class="token punctuation">&gt;</span></span> list <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        idScoreList<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span>idScore <span class="token operator">-&gt;</span> <span class="token punctuation">{</span>
            <span class="token class-name">UserDTO</span> imageDTO <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UserDTO</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">final</span> <span class="token keyword">float</span> score <span class="token operator">=</span> idScore<span class="token punctuation">.</span><span class="token function">getScore</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">final</span> <span class="token class-name">Map</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">&gt;</span></span> fieldValues <span class="token operator">=</span> idScore<span class="token punctuation">.</span><span class="token function">getFieldValues</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            imageDTO<span class="token punctuation">.</span><span class="token function">setAutoId</span><span class="token punctuation">(</span><span class="token class-name">Long</span><span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span> fieldValues<span class="token punctuation">.</span><span class="token function">getOrDefault</span><span class="token punctuation">(</span><span class="token string">"Auto_id"</span><span class="token punctuation">,</span> <span class="token string">"-1"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            imageDTO<span class="token punctuation">.</span><span class="token function">setUserId</span><span class="token punctuation">(</span><span class="token class-name">Long</span><span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span> fieldValues<span class="token punctuation">.</span><span class="token function">getOrDefault</span><span class="token punctuation">(</span><span class="token string">"user_id"</span><span class="token punctuation">,</span> <span class="token string">"-1"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            imageDTO<span class="token punctuation">.</span><span class="token function">setUserName</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span><span class="token punctuation">(</span>fieldValues<span class="token punctuation">.</span><span class="token function">getOrDefault</span><span class="token punctuation">(</span><span class="token string">"user_name"</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            imageDTO<span class="token punctuation">.</span><span class="token function">setFaceUrl</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span><span class="token punctuation">(</span>fieldValues<span class="token punctuation">.</span><span class="token function">getOrDefault</span><span class="token punctuation">(</span><span class="token string">"face_url"</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            imageDTO<span class="token punctuation">.</span><span class="token function">setFaceFeatureUrl</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">(</span><span class="token punctuation">(</span>fieldValues<span class="token punctuation">.</span><span class="token function">getOrDefault</span><span class="token punctuation">(</span><span class="token string">"face_feature_url"</span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            imageDTO<span class="token punctuation">.</span><span class="token function">setScore</span><span class="token punctuation">(</span><span class="token class-name">Math</span><span class="token punctuation">.</span><span class="token function">sqrt</span><span class="token punctuation">(</span>score<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>imageDTO<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> list<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre>
  <h2><a id="_106"></a>总结</h2>
  <p>本文展示了如何使用 <strong>EasyAi 和 Milvus</strong> 搭建一个 人脸识别应用。通过结合Java生态EasyAi和Milvus向量搜索的优势，我们可以快速的使用java搭建自己的人脸识别的项目。我们希望这篇文章对您有所帮助。同时，我们鼓励您在自己的项目中使用EasyAi和向量搜索，探索更多可能性。本文涉及的代码可以通过 <strong>Gitee</strong> 获取（<a href="https://gitee.com/fushoujiang/easy-ai-face">Easy-Ai-Face</a>）。</p>
</div>
</body>

</html>
